package com.ssy.lingxi.system.service.impl;

import com.ssy.lingxi.common.constant.CommonConstant;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.feign.paas.RoleControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.constant.MemberProcessTypeEnum;
import com.ssy.lingxi.member.merchant.api.model.vo.paas.PlatformProcessRuleVO;
import com.ssy.lingxi.member.merchant.api.model.vo.paas.RoleVO;
import com.ssy.lingxi.system.common.SystemConstant;
import com.ssy.lingxi.system.dao.*;
import com.ssy.lingxi.system.dto.request.*;
import com.ssy.lingxi.system.dto.response.BasePlatformProcessDetail;
import com.ssy.lingxi.system.dto.response.PlatformProcessResponse;
import com.ssy.lingxi.system.dto.response.RoleResponse;
import com.ssy.lingxi.system.entity.*;
import com.ssy.lingxi.system.model.constant.RoleConstant;
import com.ssy.lingxi.system.service.RoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl implements RoleService {
    @Resource
    private RoleRepository roleRepository;

    @Resource
    private MenuRepository menuRepository;

    @Resource
    private RoleMenuRepository roleMenuRepository;

    @Resource
    private MemberConfigRoleRepository memberConfigRoleRepository;

    @Resource
    private MemberConfigRepository memberConfigRepository;

    @Resource
    private BasePlatformProcessRepository basePlatformProcessRepository;

    @Resource
    private RolePlatformProcessRepository rolePlatformProcessRepository;

    @Resource
    RoleControllerFeign roleControllerFeign;

    /**
     * 分页查询角色列表
     */
    @Override
    public Wrapper<PageData<RoleResponse>> roleList(RoleRequest request) {
        Pageable pageable = PageRequest.of(request.getCurrent(), request.getPageSize(), Sort.by("id").ascending());
        Page<Role> pageList = StringUtils.hasText(request.getName()) ? roleRepository.findByNameLike(request.getName().trim(), pageable) : roleRepository.findAll(pageable);
        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(r -> {
            RoleResponse roleResponse = new RoleResponse();
            roleResponse.setId(r.getId());
            roleResponse.setMemberType(r.getMemberType());
            roleResponse.setRoleType(r.getRoleType());
            roleResponse.setServiceType(r.getServiceType());
            roleResponse.setName(r.getName());
            roleResponse.setCode(r.getCode());
            roleResponse.setDescribed(r.getDescribed());
            roleResponse.setState(r.getState());
            roleResponse.setCreateRole(r.getCreateRole());
            roleResponse.setCreateTime(r.getCreateTime());
            roleResponse.setUpdateTime(r.getUpdateTime());
            return roleResponse;
        }).collect(Collectors.toList())));
    }

    /**
     * 添加角色会员
     *
     * @author wrc
     * @date 2020/5/12
     */
    @Transactional
    @Override
    public Wrapper<Role> roleAdd(RoleAddRequest request) {
        Role role = new Role();
        role.setName(request.getName());
        role.setServiceType(request.getServiceType());
        role.setRoleType(request.getRoleType());
        role.setMemberType(request.getMemberType());
        role.setUpdateTime(System.currentTimeMillis());
        role.setCreateTime(System.currentTimeMillis());
        role.setState(RoleConstant.RoleState.ROLE_STATE_START);
        RoleVO roleVO = new RoleVO();
        roleVO.setRoleName(request.getName());
        roleVO.setBusinessTypeName(request.getServiceType());
        roleVO.setStatus(RoleConstant.RoleState.ROLE_STATE_START);
        roleVO.setMemberTypeEnum(request.getMemberType());
        roleVO.setRoleTypeEnum(request.getRoleType());
        Wrapper<Long> wrapper = roleControllerFeign.addRole(roleVO);
        if (ResponseCode.SUCCESS.getCode() != wrapper.getCode()) {
            return Wrapper.fail(wrapper.getCode(), wrapper.getMessage());
        }
        role.setId(wrapper.getData());
        Role save = roleRepository.saveAndFlush(role);
        return Wrapper.success(save);
    }

    /**
     * 修改角色会员
     *
     * @author wrc
     * @date 2020/5/12
     */
    @Transactional
    @Override
    public Wrapper<Void> roleUpdate(RoleUpdateRequest request) {
        Role role = roleRepository.findById(request.getId()).orElse(null);
        if (role == null || RoleConstant.RoleState.ROLE_STATE_START == role.getState()) {
            return Wrapper.fail("角色启用状态无法修改");
        }

        if ("平台".equals(role.getName())) {
            return Wrapper.fail("‘平台’为系统角色，不能修改或删除");
        }

        RoleVO roleVO = new RoleVO();
        roleVO.setId(request.getId());
        roleVO.setRoleName(request.getName());
        roleVO.setBusinessTypeName(request.getServiceType());
        roleVO.setRoleTypeEnum(request.getRoleType());
        roleVO.setMemberTypeEnum(request.getMemberType());
        Wrapper<?> wrapper = roleControllerFeign.updateRole(roleVO);
        if (wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(wrapper.getCode(), wrapper.getMessage());
        }

        role.setName(request.getName());
        role.setServiceType(request.getServiceType());
        role.setRoleType(request.getRoleType());
        role.setMemberType(request.getMemberType());
        role.setUpdateTime(System.currentTimeMillis());
        role.setId(request.getId());
        roleRepository.save(role);

        return Wrapper.success();
    }

    /**
     * 停用角色
     *
     * @author wrc
     * @date 2020/5/12
     */
    @Override
    public Wrapper<Void> roleStop(RoleStopRequest request) {
        Role role = roleRepository.findById(request.getId()).orElse(null);
        if (role == null) {
            return Wrapper.fail("角色不存在");
        }

        if ("平台".equals(role.getName())) {
            return Wrapper.fail("‘平台’为系统角色，不能修改或删除");
        }

        List<MemberConfigRole> configRoles = memberConfigRoleRepository.findByRoleId(role.getId());
        if (!CollectionUtils.isEmpty(configRoles)) {
            List<Long> configIds = configRoles.stream().map(MemberConfigRole::getMemberConfigId).distinct().collect(Collectors.toList());
            List<MemberConfig> configList = memberConfigRepository.findAllById(configIds);
            if (!CollectionUtils.isEmpty(configList)) {
                String configNames = configList.stream().map(MemberConfig::getAnnotationName).collect(Collectors.joining(","));
                return Wrapper.fail(role.getName() + " 已经关联了注册资料 " + configNames + "，请先解除关联");
            }
        }

        //需要判断此会员角色是否分配有角色权限
        if (roleMenuRepository.existsByRoleId(role.getId())) {
            return Wrapper.fail("此角色已分配有角色权限不能停用");
        }

        //会员服务
        RoleVO roleVO = new RoleVO();
        roleVO.setId(request.getId());
        roleVO.setStatus(RoleConstant.RoleState.ROLE_STATE_STOP);
        Wrapper<?> wrapper = roleControllerFeign.updateRoleStatus(roleVO);
        if (wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(wrapper.getCode(), wrapper.getMessage());
        }

        role.setState(RoleConstant.RoleState.ROLE_STATE_STOP);
        roleRepository.save(role);

        return Wrapper.success();
    }

    /**
     * 启用角色
     *
     * @author wrc
     * @date 2020/5/12
     */
    @Override
    public Wrapper<Void> roleStart(RoleStopRequest request) {
        Role role = roleRepository.findById(request.getId()).orElse(null);
        if (role == null) {
            return Wrapper.fail("角色不存在");
        }

        if ("平台".equals(role.getName())) {
            return Wrapper.fail("‘平台’为系统角色，不能修改或删除");
        }

        RoleVO roleVO = new RoleVO();
        roleVO.setId(request.getId());
        roleVO.setStatus(RoleConstant.RoleState.ROLE_STATE_START);
        Wrapper<?> wrapper = roleControllerFeign.updateRoleStatus(roleVO);
        if (wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(wrapper.getCode(), wrapper.getMessage());
        }

        role.setState(RoleConstant.RoleState.ROLE_STATE_START);
        roleRepository.save(role);

        return Wrapper.success();
    }

    /**
     * 删除角色
     *
     * @author wrc
     * @date 2020/5/12
     */
    @Override
    public Wrapper<Void> roleDelete(RoleStopRequest request) {
        Role role = roleRepository.findById(request.getId()).orElse(null);
        //需要判断此会员角色是否分配有角色权限
        if (role == null) {
            return Wrapper.fail("角色不存在");
        }

        if ("平台".equals(role.getName())) {
            return Wrapper.fail("‘平台’为系统角色，不能修改或删除");
        }

        if (CommonConstant.State.STATE_START.equals(role.getState())) {
            return Wrapper.fail(ResponseCode.MEMBER_START_NOT_ALLOW);
        }

        List<MemberConfigRole> configRoles = memberConfigRoleRepository.findByRoleId(role.getId());
        if (!CollectionUtils.isEmpty(configRoles)) {
            List<Long> configIds = configRoles.stream().map(MemberConfigRole::getMemberConfigId).distinct().collect(Collectors.toList());
            List<MemberConfig> configList = memberConfigRepository.findAllById(configIds);
            if (!CollectionUtils.isEmpty(configList)) {
                String configNames = configList.stream().map(MemberConfig::getAnnotationName).collect(Collectors.joining(","));
                return Wrapper.fail(role.getName() + " 已经关联了注册资料 " + configNames + "，请先解除关联");
            }
        }


        RoleVO roleVO = new RoleVO();
        roleVO.setId(request.getId());
        Wrapper<?> wrapper = roleControllerFeign.deleteRole(roleVO);
        if (wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(wrapper.getCode(), wrapper.getMessage());
        }

        roleRepository.deleteById(request.getId());
        return Wrapper.success();
    }

    /**
     * 角色详情
     *
     * @param request 接口参数
     * @author wrc
     * @date 2020/8/3
     */
    @Override
    public Wrapper<RoleResponse> roleDetails(RoleStopRequest request) {
        Optional<Role> byId = roleRepository.findById(request.getId());
        if (!byId.isPresent()) {
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }
        Role role = byId.get();
        RoleResponse roleResponse = new RoleResponse();
        BeanUtils.copyProperties(role, roleResponse);
        return Wrapper.success(roleResponse);
    }

    /**
     * 查询角色权限菜单勾选的按钮Id列表
     *
     * @param request 接口参数
     * @return 按钮Id列表
     */
    @Override
    public Wrapper<List<Long>> findRoleMenuButtons(RoleButtonRequest request) {
        Role role = roleRepository.findById(request.getRoleId()).orElse(null);
        if(role == null) {
            return Wrapper.fail("角色不存在");
        }

        List<Menu> buttons = menuRepository.findAllByParentIdAndTypeEquals(request.getMenuId(), SystemConstant.MuenType.BUTTON);
        if(CollectionUtils.isEmpty(buttons)) {
            return Wrapper.success(new ArrayList<>());
        }

        List<RoleMenu> roleMenus = roleMenuRepository.findByRoleIdAndMenuIdIn(request.getRoleId(), buttons.stream().map(Menu::getId).collect(Collectors.toList()));
        return Wrapper.success(roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList()));
    }

    /**
     * 查询角色关联的会员审核（注册）流程列表
     *
     * @param request 接口参数
     * @return 已配置的流程Id，以及所有会员审核（注册）流程列表
     */
    @Override
    public Wrapper<PlatformProcessResponse> findPlatformProcesses(RoleIdRequest request) {
        Role role = roleRepository.findById(request.getRoleId()).orElse(null);
        if (role == null) {
            return Wrapper.fail("角色不存在");
        }

        List<BasePlatformProcessDetail> basePlatformProcesses = basePlatformProcessRepository.findAll().stream().map(p -> {
            BasePlatformProcessDetail detail = new BasePlatformProcessDetail();
            detail.setProcessId(p.getId());
            detail.setName(p.getProcessName());
            detail.setProcessType(MemberProcessTypeEnum.getMsg(p.getProcessType()));
            detail.setDescription(p.getDescription());
            return detail;
        }).sorted(Comparator.comparingLong(BasePlatformProcessDetail::getProcessId)).collect(Collectors.toList());

        RolePlatformProcess rolePlatformProcess = rolePlatformProcessRepository.findFirstByRoleId(request.getRoleId());
        if (rolePlatformProcess == null) {
            return Wrapper.success(new PlatformProcessResponse(0L, basePlatformProcesses));
        } else {
            return Wrapper.success(new PlatformProcessResponse(rolePlatformProcess.getProcessId(), basePlatformProcesses));
        }
    }

    /**
     * 新增或修改角色关联的会员审核（注册）流程列表
     *
     * @param request 接口参数
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> insertOrUpdateRolePlatformProcess(RolePlatformProcessRequest request) {
        Role role = roleRepository.findById(request.getRoleId()).orElse(null);
        if (role == null) {
            return Wrapper.fail("角色不存在");
        }

        BasePlatformProcess basePlatformProcess = basePlatformProcessRepository.findById(request.getProcessId()).orElse(null);
        if (basePlatformProcess == null) {
            return Wrapper.fail("基础平台审核(会员注册)流程不存在");
        }

        //同步至会员服务
        PlatformProcessRuleVO ruleVO = new PlatformProcessRuleVO();
        ruleVO.setRoleId(request.getRoleId());
        ruleVO.setProcessKey(basePlatformProcess.getProcessKey());
        Wrapper<Void> result = roleControllerFeign.insertOrUpdateBasePlatformProcess(ruleVO);
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        //新增或修改配置
        RolePlatformProcess rolePlatformProcess = rolePlatformProcessRepository.findFirstByRoleId(request.getRoleId());
        if (rolePlatformProcess == null) {
            rolePlatformProcess = new RolePlatformProcess();
            rolePlatformProcess.setRoleId(request.getRoleId());
        }

        rolePlatformProcess.setProcessId(request.getProcessId());
        rolePlatformProcessRepository.saveAndFlush(rolePlatformProcess);

        return Wrapper.success();
    }
}
